# Figure_A01.R

# Part of the replication archive for 
#
#   Bullock, John G. 2020. "Education and Attitudes toward Redistribution in
#   the United States." British Journal of Political Science 50.


# This file produces Figure A1 in the appendix to article: "Variation in 
# Compulsory Schooling Laws across States and Years."


library(lattice)
library(grid)
source('CSL_coding.R')



##############################################################################
# PRELIMINARIES FOR PRINTING THE FIGURE 
##############################################################################
dirOutput        <- 'float_output/'
filenameStem     <- 'Figure_A01' 
PDF_title        <- 'Figure A1: Over-time and across-state variation in compulsory attendance laws'
PS_width         <- 9.5
PS_height        <- 12.0
postscriptBackground <- 'transparent'
panelwidth       <- list(.800, "inches")  
panelheight      <- list(.660, "inches")    
plotLineColor    <- 'black'
plotLineWidth    <- 1
panelBorderCol   <- 'black'
panelNumberCol   <- grey(.2)  # color of number of each panel; lower values are darker
panelBorderWidth <- .3
panelLayout      <- c(6, 8)   # columns, then rows
xBetween         <- 1.325     # space between columns
yBetween         <- 1.3175    # space between rows
panel.xlim       <- NULL                        
panel.ylim       <- c(0, 13.5)  
stripTextSize    <-  .75      # cex
xAxisTextSize    <-  .8*.87   # cex
yAxisTextSize    <-  .8*.87   # cex
axisTickSize     <- .4
xAxis            <- list(
  draw        = FALSE, 
  labels      = c(1920, 1958, 1995), 
  at          = c(1920, 1958, 1995), 
  tck         = c(axisTickSize, 0), 
  col         = panelBorderCol, 
  cex         = xAxisTextSize,
  alternating = 1, 
  relation    = 'free', 
  axs         = 'i')  # axs='i' means that there is no padding around the xlimits
yAxis            <- list(
  draw        = FALSE,
  labels      = c(2, 6, 10), 
  at          = c(2, 6, 10),
  tck         = c(axisTickSize, 0),
  col         = panelBorderCol,
  cex         = yAxisTextSize,
  alternating = 1,
  relation    = 'free',  # but the ylim will constrain all panels to same height
  rot         = 90,
  axs         = 'i')

                    

##############################################################################
# CREATE AND ORDER THE DATA FRAME
##############################################################################
# Sort the data frame so that states with the most restrictive laws are listed 
# first.
sparklineDF       <- subset(CSLdata, year%in%1910:2005 & !state%in%c('AK', 'DC', 'HI'), c(state, year, CA, CL))
tmp                <- subset(sparklineDF, year%in%2005)
tmp                <- tmp[order(tmp$CA, sort(tmp$state, decreasing = TRUE)), ]  # sort by strictness of CSLs, then by state (alphabetical order)
state.fac          <- factor(tmp$state, levels = rev(tmp$state))
sparklineDF$state <- ordered(sparklineDF$state, levels = levels(state.fac))
sparklineDF       <- sparklineDF[order(sparklineDF$state, sparklineDF$year), ]



##############################################################################
# PANEL FUNCTION
##############################################################################
sparkline.panel <- function(...) { 
  trellis.par.set("clip", list(panel="off", strip="off")) # for permitting panel.axis(outside=T, ...)
  panel.xyplot(...)

  # LABEL EACH STATE
  grid.text(
    label = levels(sparklineDF$state)[panel.number()], 
    x    = .945, 
    y    = .150, 
    just = 'right', 
    gp   = gpar(font=1, cex=.80, col=panelNumberCol)) # lower numbers are darker for grey()
  
  panel.axis(
    side     = 'top', 
    at       = c(1920, 1958, 1995), 
    labels   = FALSE,
    outside  = FALSE,
    half     = FALSE,
    tck      = .75 * axisTickSize)
  panel.axis(
    side     = 'right', 
    at       = c(2, 6, 10), 
    labels   = FALSE,
    outside  = FALSE,
    half     = FALSE,
    tck      = .75 * axisTickSize)          
  
  
  if (panel.number() %% panelLayout[1] == 1) {  # first panel in each row
    grid.text(
      label = 'years required', 
      x     = -.32, 
      y     =  .48, 
      just  = 'center', 
      gp    = gpar(font=1, cex=.705, col=panelBorderCol), 
      rot   = 90)
    panel.axis(
      side     = 'left', 
      at       = c(2, 6, 10), 
      labels   = TRUE,
      outside  = TRUE,
      tck      = axisTickSize,
      text.cex = yAxisTextSize,
      rot      = 90)
  } 
  else {
    panel.axis(
      side     = 'left', 
      at       = c(2, 6, 10), 
      labels   = FALSE,
      outside  = TRUE,
      tck      = axisTickSize)      
  }    
  
  
  if (panel.number() %in% 43:48) {  # bottom row
    panel.axis(
      side     = 'bottom', 
      at       = c(1920, 1958, 1995), 
      labels   = TRUE,
      outside  = TRUE,
      tck      = axisTickSize,
      text.cex = xAxisTextSize)
  }
  else {  # non-bottom rows
    panel.axis(
      side     = 'bottom', 
      at       = c(1920, 1958, 1995), 
      labels   = FALSE,
      outside  = TRUE,
      tck      = axisTickSize)
  }    
}



##############################################################################
# PRINT THE PDF FILE
##############################################################################
pdf(
  file   = paste0(dirOutput, filenameStem, '.pdf'), 
  width  = PS_width, 
  height = PS_height, 
  paper  = "special", 
  title  = PDF_title,
  bg     = postscriptBackground)
trellis.par.set(
  axis.components = list(     # distance between axis ticks and tick labels
    left   = list(pad1 = .50)),   
  axis.line = list(
    alpha = 1, 
    col   = panelBorderCol,   # to eliminate panel border, set col to "white"
    lty   = 1, 
    lwd   = panelBorderWidth),  
  plot.line = list(alpha = 1, col = plotLineColor, lty = 1, lwd = 1),
  superpose.line = list(
    alpha = c(1,1), 
    col   = c('black', plotLineColor), 
    lty   = c("solid", "43"), 
    lwd   = c(1, plotLineWidth)))



CSL.sparkline.plot <- xyplot(
  CA ~ year | state,
  data     = sparklineDF, 
  type     = 'l',
  panel    = sparkline.panel,
  as.table = TRUE,  # plot panels left to right, top to bottom
  layout   = panelLayout,
  ylim     = panel.ylim,
  between  = list(y=yBetween, x=xBetween),                   
  strip    = FALSE,
  scales   = list(x=xAxis, y=yAxis),
  xlab     = '',
  ylab     = '',
  par.settings = list(clip = list(panel = "off"))
)
print(CSL.sparkline.plot, panel.width=panelwidth, panel.height=panelheight)
dev.off()


if (!(Sys.which('pdfcrop')=='' | Sys.which('perl')=='')  |  'pdfcrop' %in% installed.packages()[, 'Package']) {  # if "pdfcrop" is installed 
  system(paste(
    if (Sys.info()['sysname']=='Windows') paste(Sys.getenv('Comspec'), '/c ') else '',
    'pdfcrop', 
    paste0(dirOutput, filenameStem, '.pdf'), 
    paste0(dirOutput, filenameStem, '_crop.pdf')))
  file.remove(paste0(dirOutput, filenameStem, '.pdf'))
  if (interactive()) { 
    shell.exec(paste0(normalizePath(dirOutput), filenameStem, '_crop.pdf'))
  }
}